﻿using System;

namespace Kyoh.Lib.Excel
{
    /// <summary>Microsoft Excel アプリケーション全体を表します。</summary>
	public class Excel : Component
	{
        /// <summary><see cref="Excel"/> クラスの新しいインスタンスを初期化します。</summary>
		public Excel()
			:base(Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application")), null)
		{
		}

        /// <summary>アクティブなセルを取得します。</summary>
		public Range ActiveCell
		{
			get { return Range.Create(base.GetProperty("ActiveCell"), this); }
		}
        /// <summary>アクティブなワークシートを取得します。</summary>
		public Worksheet ActiveSheet
		{
			get { return Worksheet.Create(base.GetProperty("ActiveSheet"), this); }
		}
        /// <summary>アクティブなワークブックを取得します。</summary>
		public Workbook ActiveWorkbook
		{
			get { return Workbook.Create(base.GetProperty("ActiveWorkbook"), this); }
		}

        /// <summary>保存する際に上書き確認のダイアログを表示するかどうかを取得・設定します。</summary>
		public bool AlertBeforeOverwriting
		{
			get { return (bool)base.GetProperty("AlertBeforeOverwriting"); }
			set { base.SetProperty("AlertBeforeOverwriting", value); }
		}

        /// <summary>リンク更新に確認のダイアログを表示するかどうかを取得・設定します。</summary>
		public bool AskToUpdateLinks
		{
			get { return (bool)base.GetProperty("AskToUpdateLinks"); }
			set { base.SetProperty("AskToUpdateLinks", value); }
		}

        /// <summary>使用しているExcelのビルド番号を取得します。</summary>
		public int Build
		{
			get { return (int)base.GetProperty("Build"); }
		}
        /// <summary>保存する前に数式を計算するかどうかを取得・設定します。</summary>
		public bool CalculateBeforeSave
		{
			get { return (bool)base.GetProperty("CalculateBeforeSave"); }
			set { base.SetProperty("CalculateBeforeSave", value); }
		}
        /// <summary>数式の計算方法を取得・設定します。</summary>
		public Calculation Calculation
		{
			get { return (Calculation)(int)base.GetProperty("Calculation"); }
			set { base.SetProperty("Calculation", value); }
		}
        /// <summary>使用している Excel の計算エンジンのバージョンを取得します。</summary>
		public int CalculationVersion
		{
			get { return (int)base.GetProperty("CalculationVersion"); }
		}
        /// <summary>ウィンドウのキャプションを取得・設定します。</summary>
		public string Caption
		{
			get { return (string)base.GetProperty("Caption"); }
			set { base.SetProperty("Caption", value); }
		}

        /// <summary>選択されているワークシートの列セルを取得します。</summary>
		public Range Columns
		{
			get { return Range.Create(base.GetProperty("Columns"), this); }
		}

        /// <summary>切り取り・コピーの状態を取得・設定します。</summary>
		public CutCopyMode CutCopyMode
		{
			get { return (CutCopyMode)(int)base.GetProperty("CutCopyMode"); }
			set { base.SetProperty("CutCopyMode", value); }
		}

        /// <summary>ワークブックを保存する際の標準フォーマットを取得・設定します。</summary>
		public FileFormat DefaultSaveFormat
		{
			get { return (FileFormat)(int)base.GetProperty("DefaultSaveFormat"); }
			set { base.SetProperty("DefaultSaveFormat", value); }
		}

        /// <summary>警告画面を表示するかどうかを取得・設定します。</summary>
		public bool DisplayAlerts
		{
			get { return (bool)base.GetProperty("DisplayAlerts"); }
			set { base.SetProperty("DisplayAlerts", value); }
		}

        /// <summary>処理実行中にユーザーの中断操作を受け付けるかどうかを取得・設定します。</summary>
		public EnableCancelKey EnableCancelKey
		{
			get { return (EnableCancelKey)(int)base.GetProperty("EnableCancelKey"); }
			set { base.SetProperty("EnableCancelKey", value); }
		}

        /// <summary>実行している Excel のインスタンスハンドラを取得します。</summary>
		public int InstanceHandler
		{
			get { return (int)base.GetProperty("InstanceHandler"); }
		}
        /// <summary>ウィンドウのウィンドウハンドラを取得します。</summary>
		public int WindowHandler
		{
			get { return (int)base.GetProperty("WindowHandler"); }
		}
        /// <summary>待機状態であるかどうかを取得します。</summary>
		public bool Ready
		{
			get { return (bool)base.GetProperty("Ready"); }
		}
        /// <summary>選択されているワークシートの行を取得します。</summary>
		public Range Rows
		{
			get { return Range.Create(base.GetProperty("Rows"), this); }
		}
        /// <summary>画面の自動更新を行うかどうかを取得・設定します。</summary>
		public bool ScreenUpdating
		{
			get { return (bool)base.GetProperty("ScreenUpdating"); }
			set { base.SetProperty("ScreenUpdating", value); }
		}
        /// <summary>選択されているセルを取得します。</summary>
		public Range Selection
		{
			get { return Range.Create(base.GetProperty("Selection"), this); }
		}
        /// <summary>新しいワークブックを作成した時点のシート数を取得・設定します。</summary>
		public int SheetsInNewWorkbook
		{
			get { return (int)base.GetProperty("SheetsInNewWorkbook"); }
			set { base.SetProperty("SheetsInNewWorkbook", value); }
		}
        /// <summary>ウィンドウをタスクバーに表示するかどうかを取得・設定します。</summary>
		public bool ShowWindowsInTaskbar
		{
			get { return (bool)base.GetProperty("ShowWindowsInTaskbar"); }
			set { base.SetProperty("ShowWindowsInTaskbar", value); }
		}
        /// <summary>標準フォント名を取得・設定します。</summary>
		public string StandardFont
		{
			get { return (string)base.GetProperty("StandardFont"); }
			set { base.SetProperty("StandardFont", value); }
		}
        /// <summary>標準フォントサイズを取得・設定します。</summary>
		public double StandardFontSize
		{
			get { return (double)base.GetProperty("StandardFontSize"); }
			set { base.SetProperty("StandardFontSize", value); }
		}
        /// <summary>使用しているMicrosoft Excelのバージョンを取得します。</summary>
		public string Version
		{
			get { return (string)base.GetProperty("Version"); }
		}
        /// <summary>アプリケーションを表示するかどうかを取得・設定します。</summary>
		public bool Visible
		{
			get { return (bool)base.GetProperty("Visible"); }
			set { base.SetProperty("Visible", value); }
		}
        /// <summary>ウィンドウの状態を取得・設定します。</summary>
		public WindowState WindowState
		{
			get { return (WindowState)(int)base.GetProperty("WindowState"); }
			set { base.SetProperty("WindowState", value); }
		}
        /// <summary>開いているすべてのワークブックを取得します。</summary>
		public Workbooks Workbooks
		{
			get { return Workbooks.Create(base.GetProperty("Workbooks"), this); }
		}
        /// <summary>セルで使用する関数のオブジェクトを取得します。</summary>
		public WorksheetFunction WorksheetFunction
		{
            get { return WorksheetFunction.Create(base.GetProperty("WorksheetFunction"), this); }
		}
        /// <summary>アクティブなワークブックのすべてのワークシートを取得します。</summary>
		public Worksheets Worksheets
		{
			get { return Worksheets.Create(base.GetProperty("Worksheets"), this); }
		}

        /// <summary>選択されているシート（セル）の数式をすべて計算します。</summary>
		public void Calculate()
		{
			base.InvokeMethod("Calculate");
		}

        /// <summary>開いているすべてのワークシートの数式を計算します。</summary>
		public void CalculateFull()
		{
			base.InvokeMethod("CalculateFull");
		}
        /// <summary>開いているすべてのワークシートで、データの全計算を実行し、依存を再構築します。</summary>
		public void CalculateFullRebuild()
		{
			base.InvokeMethod("CalculateFullRebuild");
		}
        /// <summary>OLEDB および OLAP データ ソースへの保留中のすべてのクエリを実行します。</summary>
		public void CalculateUntilAsyncQueriesDone()
		{
			base.InvokeMethod("CalculateUntilAsyncQueriesDone");
		}
        /// <summary>センチメートル単位の数値を、ポイント単位の値に変換します。</summary>
        /// <param name="centimeters">センチメートル長。</param>
        /// <returns>ポイント単位長。</returns>
		public double CentimetersToPoints(double centimeters)
		{
			return (double)base.InvokeMethod("CentimetersToPoints", centimeters);
		}
        /// <summary>数式文字列の参照形式を変換します。</summary>
        /// <param name="Formula">変換対象の数式文字列。</param>
        /// <param name="FromReferenceStyle">変換前の参照形式。</param>
        /// <param name="ToReferenceStyle">変換後の参照形式。</param>
        /// <param name="ToAbsolute">絶対参照にするかどうか。</param>
        /// <param name="RelativeTo">相対参照セル。</param>
        /// <returns>変換後の数式文字列。</returns>
        public string ConvertFormula(string Formula, ReferenceStyle FromReferenceStyle, ReferenceStyle? ToReferenceStyle = null, bool? ToAbsolute = null, Range RelativeTo = null)
        {
            return (string)base.InvokeMethod("ConvertFormula",
                Formula,
                FromReferenceStyle,
                ToReferenceStyle != null ? ToReferenceStyle : Type.Missing,
                (ToAbsolute != null && ToAbsolute.HasValue) ? ToAbsolute : Type.Missing,
                RelativeTo != null ? RelativeTo : Type.Missing);
        }
        /// <summary>アクティブなウィンドウに対して、ダブルクリックを実行します。</summary>
		public void DoubleClick()
		{
			base.InvokeMethod("DoubleClick");
		}

        /// <summary>Microsoft Excel のファイルを開くダイアログを表示し、ユーザの入力を受け取ります。</summary>
        /// <param name="FileFilter">ファイル フィルタに表示する文字列。</param>
        /// <param name="FilterIndex">使用するファイル フィルタの番号。</param>
        /// <param name="Title">ダイアログのキャプションに表示する文字列。</param>
        /// <param name="ButtonText">ダイアログのOKボタンに表示する文字列。</param>
        /// <param name="MultiSelect">ユーザの複数選択を許可するかどうか。</param>
        /// <returns>ユーザの選択したファイル。</returns>
        public string GetOpenFilename(string FileFilter = null, int? FilterIndex = null, string Title = null, string ButtonText = null, bool? MultiSelect = null)
        {
            object fileName;
            fileName = base.InvokeMethod("GetOpenFilename",
                FileFilter ?? Type.Missing,
                FilterIndex ?? Type.Missing,
                Title ?? Type.Missing,
                ButtonText ?? Type.Missing,
                MultiSelect ?? Type.Missing);

            if (fileName is bool)
                return null;
            else
                return (string)fileName;
        }
		
        /// <summary>Microsoft Excel のファイルを保存ダイアログを表示し、ユーザの入力を受け取ります。</summary>
        /// <param name="InitialFilename">初期状態で表示するファイル名。</param>
        /// <param name="FileFilter">ファイル フィルタに表示する文字列。</param>
        /// <param name="FilterIndex">使用するファイル フィルタの番号。</param>
        /// <param name="Title">ダイアログのキャプションに表示する文字列。</param>
        /// <param name="ButtonText">ダイアログのOKボタンに表示する文字列。</param>
        /// <returns>ユーザの選択したファイル。</returns>
        public string GetSaveAsFilename(string InitialFilename = null, string FileFilter = null, int? FilterIndex = null, string Title = null, string ButtonText = null)
        {
            object fileName;
            fileName = base.InvokeMethod("GetSaveAsFilename",
                InitialFilename ?? Type.Missing,
                FileFilter ?? Type.Missing,
                FilterIndex ?? Type.Missing,
                Title ?? Type.Missing,
                ButtonText ?? Type.Missing);

            if (fileName is bool)
                return null;
            else
                return (string)fileName;
        }

        /// <summary>インチ単位の数値を、ポイント単位の値に変換します。</summary>
        /// <param name="inches">インチ長。</param>
        /// <returns>ポイント単位長。</returns>
		public double InchesToPoints(double inches)
		{
			return (double)base.InvokeMethod("InchesToPoints", inches);
		}

        /// <summary>ユーザの入力ダイアログを表示し、ユーザの入力を受け取ります。</summary>
        /// <param name="Prompt">プロンプト文字列。</param>
        /// <param name="Title">ダイアログのキャプションに表示する文字列。</param>
        /// <param name="Default">初期状態の入力文字列。</param>
        /// <param name="Left">表示位置の左端値。</param>
        /// <param name="Top">表示位置の上端値。</param>
        /// <param name="HelpFile">ヘルプファイル名。</param>
        /// <param name="HelpContextID">ヘルプコンテキストID。</param>
        /// <param name="Type">入力形式。</param>
        /// <returns>ユーザの入力値。</returns>
        public object InputBox(string Prompt, string Title = null, string Default = null, int? Left = null, int? Top = null, string HelpFile = null, int? HelpContextID = null, InputType Type = InputType.None)
        {
            object input = 
                base.InvokeMethod("InputBox",
                    Prompt,
                    Title ?? System.Type.Missing,
                    Default ?? System.Type.Missing,
                    Left ?? System.Type.Missing,
                    Top ?? System.Type.Missing,
                    HelpFile ?? System.Type.Missing,
                    HelpContextID ?? System.Type.Missing,
                    (Type == InputType.None ? System.Type.Missing : Type));
            if (Reflect.GetComClassName(input) == "Range")
                return Range.Create(input, this);
            else
                return input;
        }

        /// <summary>開いているワークシートを保存します。</summary>
        /// <param name="filename">保存するファイル名。</param>
		public void Save(string filename = null)
		{
			base.InvokeMethod("Save", filename == null ? Type.Missing : filename);
		}
		
        /// <summary>アクティブなウィンドウに、キー入力を送信します。</summary>
        /// <param name="Keys">送信するキー文字列。</param>
        /// <param name="Wait">送信した結果を待つ場合は <c>true</c>。それ以外の場合は <c>false</c>。</param>
		public void SendKeys(string Keys, bool? Wait = null)
		{
            base.InvokeMethod("SendKeys", Keys, Wait ?? Type.Missing);
		}

        /// <summary>最後の操作を取り消します。</summary>
		public void Undo()
		{
			base.InvokeMethod("Undo");
		}

        /// <summary>セル範囲の積集合を取得します。</summary>
        /// <param name="arg1">1つめのセル範囲を指定します。</param>
        /// <param name="arg2">2つめのセル範囲を指定します。</param>
        /// <param name="args">3つめ以降のセル範囲を指定します。</param>
        /// <returns>指定したセルの積集合セル。</returns>
		public Range Intersect(
			Range arg1,
			Range arg2,
			params Range[] args)
		{
			return (Range)base.InvokeMethod(
				"Intersect",
				arg1.ExcelComObject,
				arg2.ExcelComObject,
				args.Length > 0 ? args[0].ExcelComObject : Type.Missing,
				args.Length > 1 ? args[1].ExcelComObject : Type.Missing,
				args.Length > 2 ? args[2].ExcelComObject : Type.Missing,
				args.Length > 3 ? args[3].ExcelComObject : Type.Missing,
				args.Length > 4 ? args[4].ExcelComObject : Type.Missing,
				args.Length > 5 ? args[5].ExcelComObject : Type.Missing,
				args.Length > 6 ? args[6].ExcelComObject : Type.Missing,
				args.Length > 7 ? args[7].ExcelComObject : Type.Missing,
				args.Length > 8 ? args[8].ExcelComObject : Type.Missing,
				args.Length > 9 ? args[9].ExcelComObject : Type.Missing,
				args.Length > 10 ? args[10].ExcelComObject : Type.Missing,
				args.Length > 11 ? args[11].ExcelComObject : Type.Missing,
				args.Length > 12 ? args[12].ExcelComObject : Type.Missing,
				args.Length > 13 ? args[13].ExcelComObject : Type.Missing,
				args.Length > 14 ? args[14].ExcelComObject : Type.Missing,
				args.Length > 15 ? args[15].ExcelComObject : Type.Missing,
				args.Length > 16 ? args[16].ExcelComObject : Type.Missing,
				args.Length > 17 ? args[17].ExcelComObject : Type.Missing,
				args.Length > 18 ? args[18].ExcelComObject : Type.Missing,
				args.Length > 19 ? args[19].ExcelComObject : Type.Missing,
				args.Length > 20 ? args[20].ExcelComObject : Type.Missing,
				args.Length > 21 ? args[21].ExcelComObject : Type.Missing,
				args.Length > 22 ? args[22].ExcelComObject : Type.Missing,
				args.Length > 23 ? args[23].ExcelComObject : Type.Missing,
				args.Length > 24 ? args[24].ExcelComObject : Type.Missing,
				args.Length > 25 ? args[25].ExcelComObject : Type.Missing,
				args.Length > 26 ? args[26].ExcelComObject : Type.Missing,
				args.Length > 27 ? args[27].ExcelComObject : Type.Missing);
		}

        /// <summary>セル範囲の和集合を取得します。</summary>
        /// <param name="arg1">1つめのセル範囲を指定します。</param>
        /// <param name="arg2">2つめのセル範囲を指定します。</param>
        /// <param name="args">3つめ以降のセル範囲を指定します。</param>
        /// <returns>指定したセルの和集合セル。</returns>
        public Range Union(
			Range arg1,
			Range arg2,
			params Range[] args)
		{
			return (Range)base.InvokeMethod(
				"Union",
				arg1.ExcelComObject,
				arg2.ExcelComObject,
				args.Length > 0 ? args[0].ExcelComObject : Type.Missing,
				args.Length > 1 ? args[1].ExcelComObject : Type.Missing,
				args.Length > 2 ? args[2].ExcelComObject : Type.Missing,
				args.Length > 3 ? args[3].ExcelComObject : Type.Missing,
				args.Length > 4 ? args[4].ExcelComObject : Type.Missing,
				args.Length > 5 ? args[5].ExcelComObject : Type.Missing,
				args.Length > 6 ? args[6].ExcelComObject : Type.Missing,
				args.Length > 7 ? args[7].ExcelComObject : Type.Missing,
				args.Length > 8 ? args[8].ExcelComObject : Type.Missing,
				args.Length > 9 ? args[9].ExcelComObject : Type.Missing,
				args.Length > 10 ? args[10].ExcelComObject : Type.Missing,
				args.Length > 11 ? args[11].ExcelComObject : Type.Missing,
				args.Length > 12 ? args[12].ExcelComObject : Type.Missing,
				args.Length > 13 ? args[13].ExcelComObject : Type.Missing,
				args.Length > 14 ? args[14].ExcelComObject : Type.Missing,
				args.Length > 15 ? args[15].ExcelComObject : Type.Missing,
				args.Length > 16 ? args[16].ExcelComObject : Type.Missing,
				args.Length > 17 ? args[17].ExcelComObject : Type.Missing,
				args.Length > 18 ? args[18].ExcelComObject : Type.Missing,
				args.Length > 19 ? args[19].ExcelComObject : Type.Missing,
				args.Length > 20 ? args[20].ExcelComObject : Type.Missing,
				args.Length > 21 ? args[21].ExcelComObject : Type.Missing,
				args.Length > 22 ? args[22].ExcelComObject : Type.Missing,
				args.Length > 23 ? args[23].ExcelComObject : Type.Missing,
				args.Length > 24 ? args[24].ExcelComObject : Type.Missing,
				args.Length > 25 ? args[25].ExcelComObject : Type.Missing,
				args.Length > 26 ? args[26].ExcelComObject : Type.Missing,
				args.Length > 27 ? args[27].ExcelComObject : Type.Missing);
		}
		
        /// <summary>オブジェクトを破棄します。</summary>
        /// <param name="disposing">明示的な破棄の場合には <c>true</c> 、それ以外の場合は <c>false</c> 。</param>
		protected override void Dispose(bool disposing)
		{
            if (disposing)
            {
                base.SetProperty("DisplayAlerts", false);
                base.InvokeMethod("Quit");
            }
			base.Dispose(disposing);
		}
	}
}
